package GUI;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Vector;

import game.Item;
import game.ItemContainer;
import game.Item.ItemType;

import javax.swing.JPanel;

public class ItemContainerView extends JPanel implements ComponentListener, MouseListener, MouseWheelListener, ActionListener
{
	private static final long serialVersionUID = -4287594935988943939L;

	private class ContainerItem
	{
		public Item item = null;
		public boolean selected = false;
	}
	
	private ItemContainer cont = null;
	private boolean allowTooltips = true;
	private int filterHeight = 30;
	private int filterWidth = 50;
	private int itemHeight = 50;
	private int itemCount = 0;
	private int selFilter = 0;
	private int sbWidth = 5;
	private int off = 0;
	private int[] offsets = new int[5];
	private String[] txtFilter = new String[] { "All", "Weapons", "Defense", "Potions", "Misc" };
	private ButtonSkin skin = null;
	private Window tooltipParentWindow = null;
	private static final Color magicBlue = new Color(128, 128, 255);
	private static BufferedImage wBack = null, wCover = null;
	
	public Window getTooltipParentWindow() {
		return tooltipParentWindow;
	}

	public void setTooltipParentWindow(Window tooltipParentWindow) {
		this.tooltipParentWindow = tooltipParentWindow;
	}

	private Vector<ContainerItem> list = new Vector<ContainerItem>();
	private Vector<Vector<ContainerItem>> lists = new Vector<Vector<ContainerItem>>();
	
	private Paint grad = new LinearGradientPaint(0.0f, 0.0f, 0.0f, 50.0f,
			new float[] { 0.0f, 1.0f }, new Color[] { new Color(0, 0, 128), new Color(0, 0, 32) },
			java.awt.MultipleGradientPaint.CycleMethod.REPEAT);
	
	public ItemContainerView(ItemContainer container)
	{
		cont = container;
		skin = ButtonSkin.getButtonByTag("Button1");
		lists.add(new Vector<ItemContainerView.ContainerItem>());
		lists.add(new Vector<ItemContainerView.ContainerItem>());
		lists.add(new Vector<ItemContainerView.ContainerItem>());
		lists.add(new Vector<ItemContainerView.ContainerItem>());
		lists.add(new Vector<ItemContainerView.ContainerItem>());
		list = lists.get(0);
		refreshLists();
		this.setBackground(new Color(64, 64, 64));
		this.addMouseListener(this);
		this.addMouseWheelListener(this);
		
		if(wBack == null) wBack = ImageStorage.getImage("GUI/weight-bar.png");
		if(wCover == null) wCover = ImageStorage.getImage("GUI/bar-cover.png");
		
		if(cont != null)
		{
			cont.addActionListener(this);
		}
	}
	
	public void refreshLists()
	{
		list.clear();
		if(cont == null) return;
		
		ArrayList<Item> l = cont.GetItemList();
		
		
		for(int sf = 0; sf < 5; ++sf)
		{
			lists.get(sf).clear();
			for(Item itm : l)
			{
				boolean add = false;
				switch(sf)
				{
				case 0: // All
					add = true;
					break;
				case 1: // Weapons
					add = (itm.getType() == ItemType.WEAPON);
					break;
				case 2: // Defense
					add = (itm.getType() == ItemType.SHIELD) ||
						(itm.getType() == ItemType.ARMOR) ||
						(itm.getType() == ItemType.HELMET);
					break;
				case 3: // Potions
					add = (itm.getType() == ItemType.POTION);
					break;
				case 4: // Miselanjke
					add = (itm.getType() == ItemType.CHARM) || (itm.getType() == ItemType.SPECIAL);
					break;
				}
				
				if(add)
				{
					ContainerItem ci = new ContainerItem();
					ci.item = itm;
					ci.selected = false;
					lists.get(sf).add(ci);
				}
			}
			
			if(offsets[sf] > lists.get(sf).size() - itemCount) off = lists.get(sf).size() - itemCount;
			if(offsets[sf] < 0) offsets[sf] = 0;
		}
		
		off = offsets[selFilter];
	}
	
	public void paint(Graphics gg)
	{
		Graphics2D g = (Graphics2D)gg;
		g.setColor(this.getBackground());
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		
		filterWidth = this.getWidth() / 5;
		for(int i = 0; i < 5; ++i)
		{
			skin.drawSimpleButton(g, txtFilter[i], 
					i * filterWidth, 0, filterWidth, filterHeight, i == selFilter);
			//g.setColor(i == selFilter ? Color.red : Color.yellow);
			//g.fillRect(i * filterWidth, 0, filterWidth, filterHeight);
		}
		
		paintList(g);
		
		if(wCover != null && wBack != null && cont != null)
		{
			HUD.drawBarWH(g, wBack, wCover, 0, this.getHeight() - 20, 
					this.getWidth(), 20, cont.getMaxWeight(), cont.getWeight());
		}
		
		if(cont != null)
		{
			ButtonSkin.drawText(g, "Weight : " + cont.getWeight() + " / " + cont.getMaxWeight(),
					Color.white, 0, this.getHeight() - 20, this.getWidth(), 20,
					ButtonSkin.CENTER, true);
		}
	}
	
	public void paintList(Graphics2D g)
	{
		int remH = (this.getHeight() - filterHeight - 20);
		g.translate(0, filterHeight);
		itemCount = remH / itemHeight; 
		
		for(int i = 0, n = off; i < itemCount; ++i, ++n)
		{
			if(n >= 0 && n < list.size())
			{
				if(list.get(n).selected)
				{
					g.setPaint(grad);
					g.fillRect(0, i * itemHeight, this.getWidth(), itemHeight);
				}
				
				BufferedImage image = list.get(n).item.getImage();
				if(image != null)
				{
					g.drawImage(image, 5, i * itemHeight, itemHeight, itemHeight, null);
				}
				
				ButtonSkin.drawText(g, list.get(n).item.getName(),
						list.get(n).item.getEffects().size() > 0 && 
						list.get(n).item.getType() != Item.ItemType.POTION ? magicBlue : Color.white,
						30, i * itemHeight, this.getWidth(), itemHeight, ButtonSkin.LEFT, false);
			}
		}
		
		if(list.size() > itemCount)
		{
			g.setColor(Color.blue);
			float factor = (float)itemCount / list.size();
			int sbSize = (int) (factor * (float)remH);
			int bar = remH - sbSize;
			int oY = (int) (((float)off / (float)(list.size() - itemCount)) * (float)bar);
			g.fillRect(this.getWidth() - sbWidth - 3, oY, sbWidth, sbSize);
		}
		
		g.translate(0, -filterHeight);
	}

	@Override
	public void componentResized(ComponentEvent arg0)
	{
		//filterWidth = this.getWidth() / 5;
	}
	
	@Override
	public void componentHidden(ComponentEvent arg0){}
	@Override
	public void componentMoved(ComponentEvent arg0){}
	@Override
	public void componentShown(ComponentEvent arg0){}
	@Override
	public void mouseClicked(MouseEvent e){}
	@Override
	public void mouseEntered(MouseEvent e){}
	@Override
	public void mouseExited(MouseEvent e){}
	@Override
	public void mousePressed(MouseEvent e){}

	public Vector<Item> getSelectedItems()
	{
		Vector<Item> sel = new Vector<Item>();
		for(ContainerItem ci : list)
			if(ci.selected)
				sel.add(ci.item);
		return sel;
	}
	
	@Override
	public void mouseReleased(MouseEvent e)
	{
		if(e.getY() < filterHeight)
		{
			int oldFilter = selFilter;
			selFilter = e.getX() / filterWidth;
			if(selFilter > 4) selFilter = 4;
			if(selFilter < 0) selFilter = 0;
			
			if(oldFilter != selFilter)
			{
				list = lists.get(selFilter);
				offsets[oldFilter] = off;
				off = offsets[selFilter];
				repaint();
			}
		}
		else
		{
			int n = (e.getY() - filterHeight) / itemHeight;
			if(n < 0 || n >= itemCount) return;
			
			int i = n + off;
			if(i >= 0 && i < list.size())
			{
				if(e.isShiftDown())
				{
					list.get(i).selected = !list.get(i).selected;
				}
				else
				{
					for(int x = 0; x < list.size(); ++x)
						list.get(x).selected = x == i;
					
					if(e.getButton() == MouseEvent.BUTTON3)
					{
						//System.out.println(list.get(i).item.getHTML());
						if(tooltipParentWindow == null)
						{
							if(this.getTopLevelAncestor() instanceof Window)
								tooltipParentWindow = (Window) this.getTopLevelAncestor();
						}
						
						if(tooltipParentWindow != null)
							InfoWindow.showToolTip(list.get(i).item.getHTML(), e.getXOnScreen(), e.getYOnScreen(), tooltipParentWindow);
					}
				}
				
				repaint();
			}
		}
	}

	@Override
	public void mouseWheelMoved(MouseWheelEvent arg0) {
		off += arg0.getWheelRotation();
		
		if(off > list.size() - itemCount) off = list.size() - itemCount;
		if(off < 0) off = 0;
		
		repaint();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		refreshLists();
		repaint();
	}
	
	public ItemContainer getItemContainer()
	{
		return cont;
	}
	
	public void setItemContainer(ItemContainer c)
	{
		if(cont != null) cont.removeActionListener(this);
		cont = c;
		c.addActionListener(this);
		refreshLists();
		repaint();
	}
	
	public void selectAll()
	{
		for(ContainerItem ci : list)
			ci.selected = true;
		repaint();
	}
	
	public void selectNone()
	{
		for(ContainerItem ci : list)
			ci.selected = false;
		repaint();
	}
	
	public void selectItems(Vector<Item> items)
	{
		for(ContainerItem ci : list)
			ci.selected = items.contains(ci.item);
		repaint();
	}
}
